﻿#include "Caption.h"

#include <fstream>

Caption::Caption(
	int frame_size_x,
	int frame_size_y,
	double frame_rate,
	double begin_secs,
	double end_secs,
	size_t total_frames,
	int loc_x,
	int loc_y,
	std::string caption_path,
	uint32_t font_size,
	std::string font_path,
	int32_t font_index,
	Color color,
	uint8_t alpha,
	std::string anchor_type,
	int anchor_x,
	int anchor_y,
	bool horizontal,
	float line_spacing,
	std::string alignment_type,
	FT_Library font_lib
) :MLObj(frame_size_x, frame_size_y, frame_rate) {
	std::cout << "正在初始化字幕……" << std::endl;
	_start_frame_count = rint(begin_secs * frame_rate);
	_end_frame_count = total_frames - rint(end_secs * frame_rate);
	_text_glsl = Utils::activateShader("./GLSL/TextVertex.glsl", "./GLSL/TextFragment.glsl");
	_mix_glsl = Utils::activateShader("./GLSL/MixVertex.glsl", "./GLSL/MixFragment.glsl");
	_text_frames = _read_lyrics(caption_path, frame_rate);
	Anchor anchor = _get_anchor_type(anchor_type);
	TextAlignment alignment = _get_alignment_type(alignment_type);
	_text = _get_text_obj(font_size, font_path, font_index, color, alpha, frame_size_x, frame_size_y, loc_x, loc_y,
	                      anchor, anchor_x, anchor_y, horizontal, line_spacing, alignment, _text_glsl, font_lib);
	glGenFramebuffers(1, &_fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, _fbo);

	// 创建纹理附件
	glGenTextures(1, &_texture);
	glBindTexture(GL_TEXTURE_2D, _texture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, frame_size_x, frame_size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);

	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		throw "";
	}
}

void Caption::get_frame(size_t frame_index, MLFrame& frame) {
	if (frame_index < _start_frame_count || frame_index > _end_frame_count) {
		return;
	}
	frame_index -= _start_frame_count;
	_CaptionFrame text_frame = _text_frames.front();
	if (!_buffered) {
		Utils::clearFrame(_fbo);
		Drawer::drawText(_text, text_frame.content, _fbo, _texture);
		_buffered = true;
	}
	/*if (frame_index == 1200) {
		FrameWriter writer = Utils::initFrameWriter(_frame_size_x, _frame_size_y);
		uint8_t* frame_bitmap = Utils::getFrame(writer, _fbo, _texture);
		cv::Mat bitmap_mat = cv::Mat(cv::Size(_frame_size_x, _frame_size_y), CV_8UC3, frame_bitmap);
		cv::Mat bitmap_mat_bgr = cv::Mat(_frame_size_x, _frame_size_y, CV_8UC3);
		cv::cvtColor(bitmap_mat, bitmap_mat_bgr, cv::COLOR_RGB2BGR);
		cv::imwrite("C:\\Users\\muche\\Desktop\\Caption.png", bitmap_mat_bgr);
		std::cout << "FBO=" << _fbo << std::endl;
	}*/
	if (frame_index >= text_frame.end_frame_count) {
		_text_frames.pop();
		_buffered = false;
	}
	frame.mix(_fbo, _texture, 0, _mix_glsl);
	/*if (frame_index == 1200) {
		FrameWriter writer = Utils::initFrameWriter(_frame_size_x, _frame_size_y);
		uint8_t* frame_bitmap = frame.getFrame(writer);
		cv::Mat bitmap_mat = cv::Mat(cv::Size(_frame_size_x, _frame_size_y), CV_8UC3, frame_bitmap);
		cv::Mat bitmap_mat_bgr = cv::Mat(_frame_size_x, _frame_size_y, CV_8UC3);
		cv::cvtColor(bitmap_mat, bitmap_mat_bgr, cv::COLOR_RGB2BGR);
		cv::imwrite("C:\\Users\\muche\\Desktop\\Caption2.png", bitmap_mat_bgr);
		std::cout << "FBO=" << frame.fbo << std::endl;
	}*/
}

Text Caption::_get_text_obj(
	uint32_t font_size,
	std::string font_path,
	int32_t font_index,
	Color color,
	uint8_t alpha,
	int frame_size_x,
	int frame_size_y,
	int loc_x,
	int loc_y,
	Anchor anchor,
	int anchor_x,
	int anchor_y,
	bool horizontal,
	float line_spacing,
	TextAlignment alignment,
	GLuint text_glsl,
	FT_Library font_lib
) {
	FT_Face _font;
	if (FT_New_Face(font_lib, font_path.c_str(), font_index, &_font)) {
		throw "加载字体失败。";
	}
	if (FT_Set_Pixel_Sizes(_font, font_size, font_size)) {
		throw "设置字体大小失败。";
	}
	return Drawer::initText(_font, color, alpha, frame_size_x, frame_size_y, loc_x, loc_y, anchor, anchor_x, anchor_y,
	                        horizontal, line_spacing, alignment, text_glsl);
}

std::queue<_CaptionFrame> Caption::_read_lyrics(std::string caption_path, double frame_rate) {
	std::ifstream fs;
	fs.open(caption_path, std::ios::in);
	if (!fs.is_open()) {
		char to_throw[384];
		const char* to_throw_fmt = "文件打开失败：%s。";
		sprintf(to_throw, to_throw_fmt, caption_path.c_str());
		throw to_throw;
	}
	std::string line;
	std::queue<_CaptionFrame> text_frames;
	while (std::getline(fs, line)) {
		try {
			_CaptionFrame frame = Caption::_read_lyric_line(line, frame_rate);
			text_frames.push(frame);
		}
		catch (std::string e) {
			std::cout << "[INFO]" << e << std::endl;
		}
	}
	fs.close();
	return Caption::_connect_lyrics(text_frames);
}

_CaptionFrame Caption::_read_lyric_line(std::string line, double frame_rate) {
	// 检查行是否以'['开头
	if (line.empty()) {
		throw "已跳过空行。" + line;
	}

	if (line[0] != '[') {
		throw "已跳过非法的行：" + line;
	}

	// 查找第一个']'的位置
	size_t endBracket = line.find(']');
	if (endBracket == std::string::npos || endBracket < 2) {
		throw "已跳过非法的行：" + line;
	}

	// 提取括号内的内容
	std::string tag = line.substr(1, endBracket - 1);

	// 检查标签内容是否为时间戳（应包含':'且由数字和分隔符组成）
	bool hasColon = (tag.find(':') != std::string::npos);
	bool allValid = std::all_of(tag.begin(), tag.end(), [](char c) {
		return std::isdigit(c) || c == ':' || c == '.';
	});

	if (!hasColon || !allValid) {
		throw "已跳过无时间戳的行：" + line;
	}

	// 解析时间戳：支持 [mm:ss.xx] 或 [mm:ss] 格式
	int minutes = 0, seconds = 0, hundredths = 0;
	int parsed = sscanf(tag.c_str(), "%d:%d.%d", &minutes, &seconds, &hundredths);

	// 处理只有分秒的情况（无百分秒）
	if (parsed < 2) {
		throw "已跳过时间戳格式错误的行：" + line;
	}
	if (parsed == 2) {  // 未解析到百分秒
		hundredths = 0;
	}

	// 验证时间范围
	if (minutes < 0 || seconds < 0 || seconds >= 60 || hundredths < 0 || hundredths >= 100) {
		throw "已跳过时间戳值错误的行：" + line;
	}

	// 转换为0.01秒单位
	double timestamp = static_cast<double>((minutes * 60 + seconds) * 100 + hundredths);

	// 提取歌词（跳过后续空格）
	std::string lyric = line.substr(endBracket + 1);
	size_t firstChar = lyric.find_first_not_of(" \t");
	if (firstChar != std::string::npos) {
		lyric = lyric.substr(firstChar);
	}
	else {
		lyric.clear();  // 行尾无歌词
	}

	size_t start_frame_count = rint(timestamp * frame_rate / 100);
	size_t end_frame_count = -1;
	return _CaptionFrame{ start_frame_count,end_frame_count,lyric };
}

std::queue<_CaptionFrame> Caption::_connect_lyrics(std::queue<_CaptionFrame>& frames) {
	std::queue<_CaptionFrame> connected_frames;
	_CaptionFrame last_frame;
	_CaptionFrame current_frame = frames.front();
	frames.pop();
	if (current_frame.start_frame_count > 0) {
		last_frame = _CaptionFrame{ 0,current_frame.start_frame_count,"" };
		connected_frames.push(last_frame);
	}
	while (!frames.empty()) {
		last_frame = current_frame;
		current_frame = frames.front();
		frames.pop();
		if (last_frame.start_frame_count == current_frame.start_frame_count) {
			last_frame.content = last_frame.content + "\n" + current_frame.content;
			current_frame = last_frame;
			continue;
		}
		last_frame.end_frame_count = current_frame.start_frame_count;
		connected_frames.push(last_frame);
	}
	connected_frames.push(current_frame);
	return connected_frames;
}

Anchor Caption::_get_anchor_type(std::string anchor_type) {
	Anchor anchor;
	if (anchor_type == "nw")anchor = Anchor::NW;
	else if (anchor_type == "n")anchor = Anchor::N;
	else if (anchor_type == "ne")anchor = Anchor::NE;
	else if (anchor_type == "w")anchor = Anchor::W;
	else if (anchor_type == "center")anchor = Anchor::CENTER;
	else if (anchor_type == "e")anchor = Anchor::E;
	else if (anchor_type == "sw")anchor = Anchor::SW;
	else if (anchor_type == "s")anchor = Anchor::S;
	else if (anchor_type == "se")anchor = Anchor::SE;
	else if (anchor_type == "free")anchor = Anchor::FREE;
	else {
		anchor = Anchor::CENTER;
		std::cout << "[INFO]未知的锚点位置类型，将使用默认值（中心）。" << std::endl;
	}
	return anchor;
}

TextAlignment Caption::_get_alignment_type(std::string type) {
	TextAlignment alignment;
	if (type == "top")alignment = TextAlignment::TOP;
	else if (type == "bottom")alignment = TextAlignment::BOTTOM;
	else if (type == "center")alignment = TextAlignment::CENTER;
	else if (type == "left")alignment = TextAlignment::LEFT;
	else if (type == "right")alignment = TextAlignment::RIGHT;
	else {
		alignment = TextAlignment::CENTER;
		std::cout << "[INFO]未知的字符对齐类型，将使用默认值（中心）。" << std::endl;
	}
	return alignment;
}